package ace.cmp.controller.spring.data.jdbc.querydsl.rsql.core;

import ace.cmp.data.spring.data.jdbc.querydsl.rsql.core.manager.Manager;
import ace.cmp.data.spring.data.jdbc.querydsl.rsql.core.manager.impl.DefaultManagerConstructArgs;
import ace.cmp.data.spring.data.jdbc.querydsl.rsql.core.manager.spring.ManagerSpringFactory;
import ace.cmp.spring.data.jdbc.querydsl.core.QuerydslRelationHelper;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ResolvableType;

/**
 * @author caspar
 * @date 2023/4/12 17:30
 */
@Slf4j
public abstract class AbstractController<EntityT> implements InitializingBean {

  @Autowired
  private ManagerSpringFactory entityManagerSpringFactory;

  @Autowired
  @Getter(AccessLevel.PROTECTED)
  private QuerydslRelationHelper querydslRelationHelper;

  @Getter(value = AccessLevel.PROTECTED)
  @Setter(value = AccessLevel.PROTECTED)
  private Class idClass;

  @Getter(value = AccessLevel.PROTECTED)
  @Setter(value = AccessLevel.PROTECTED)
  private Class<EntityT> entityClass;

  @Getter(value = AccessLevel.PROTECTED)
  @Setter(value = AccessLevel.PROTECTED)
  private Manager<EntityT, ?> manager;

  protected AbstractController() {
    ResolvableType resolvableType = ResolvableType.forType(this.getClass());
    this.entityClass = (Class<EntityT>) resolvableType.getSuperType().getGeneric(0).getRawClass();
  }

  @Override
  public void afterPropertiesSet() throws Exception {
    this.idClass = (Class) this.getQuerydslRelationHelper()
        .getPrimaryKeyPath(this.getEntityClass())
        .getType();

    this.initManager();
  }

  protected void initManager() {
    DefaultManagerConstructArgs args = new DefaultManagerConstructArgs<>();
    args.setIdClass(this.getIdClass());
    args.setEntityClass(this.getEntityClass());

    Manager<EntityT, ?> manager = entityManagerSpringFactory.getOrCreate(args);
    this.manager = manager;
  }
}
